var logger = require('pomelo-logger').getLogger('pomelo', __filename);

/**
 * Filter service.  过滤器服务
 * Register and fire before and after filters.
 */
var Service = function() {
  this.befores = [];    // before filters before过滤器链
  this.afters = [];     // after filters  after过滤器链
};

module.exports = Service;

Service.prototype.name = 'filter';

/**
 * Add before filter into the filter chain.
 * 添加before过滤器到过滤器链中(其实就是个数组)
 *
 * @param filter {Object|Function} filter instance or filter function.
 */
Service.prototype.before = function(filter){
  this.befores.push(filter);//添加到数组中 在尾部插入
};

/**
 * Add after filter into the filter chain.
 * 添加after过滤器到过滤器链中(其实也是个数组)
 * @param filter {Object|Function} filter instance or filter function.
 */
Service.prototype.after = function(filter){
  this.afters.unshift(filter);//在头部插入 注意这里跟插入before过滤器的不同之处
};

/**
 * TODO: other insert method for filter? such as unshift
 */

/**
 * Do the before filter.
 * 启动before过滤器
 * Fail over if any filter pass err parameter to the next function.
 * 如果任何过滤器传递了err参数给next函数则失败
 *
 * @param msg {Object} clienet request msg
 * @param session {Object} a session object for current request
 * @param cb {Function} cb(err) callback function to invoke next chain node
 */
Service.prototype.beforeFilter = function(msg, session, cb) {
  var index = 0, self = this;
  var next = function(err, resp, opts) {//定义next函数，用于递归遍历所有的触发器 这的参数名字是不是写错了？？
    if(err || index >= self.befores.length) {//如果出错或者已经遍历完所有before过滤器
      cb(err, resp, opts);//调用回调返回  还有这的参数名字也错了，因为这里的resp毫无意义(其实是有意义的，当出错时，可以返回一个resp作为对客户端的返回)
      return;
    }

    var handler = self.befores[index++];//取得过滤器 可能是过滤函数 也可能是个对象 其before方法是过滤函数
    if(typeof handler === 'function') {//handler是过滤函数
      handler(msg, session, next);//调用handler
    } else if(typeof handler.before === 'function') {//handler.before是过滤函数
      handler.before(msg, session, next);//调用handler.before
    } else {//都不是函数，则报错
      logger.error('meet invalid before filter, handler or handler.before should be function.');
      //遇到非法的before过滤器，handler或者是handler.before应该是个函数
      next(new Error('invalid before filter.'));
    }
  }; //end of next

  next();//第一次触发
};

/**
 * Do after filter chain.
 * 启动after过滤器
 * Give server a chance to do clean up jobs after request responsed. //给服务器一个机会做一些清理任务（在请求响应之后）
 * After filter can not change the request flow before.             //after过滤器不能修改之前的请求流
 * After filter should call the next callback to let the request pass to next after filter.
 *  //after过滤器应该调用next回调让请求传递到下一个after过滤器
 *
 * @param err {Object} error object
 * @param session {Object} session object for current request
 * @param {Object} resp response object send to client
 * @param cb {Function} cb(err) callback function to invoke next chain node
 */
Service.prototype.afterFilter = function(err, msg, session, resp, cb) {
  var index = 0, self = this;
  function next(err) {//定义next函数
    //if done
    if(index >= self.afters.length) {//遍历after过滤器完成
      cb(err);
      return;
    }
    //同before过滤器的写法一样
    var handler = self.afters[index++];
    if(typeof handler === 'function') {
      handler(err, msg, session, resp, next);
    } else if(typeof handler.after === 'function') {
      handler.after(err, msg, session, resp, next);
    } else {
      logger.error('meet invalid after filter, handler or handler.before should be function.');
      next(new Error('invalid after filter.'));
    }
  } //end of next

  next(err);//第一次触发
};
